import { ElMessage, ElNotification } from "element-plus";
import { useAccountStore } from "../stores/account";
import { apiConfig } from "./config";
class WSManager {
    constructor() {
        this.ws = null;
        this.url = "";
        this.reconnectInterval = 3000;
        this.reconnectTimer = null;
        this.messageHandlers = new Set();
        this.isManualClose = false;
        this.accountStore = null;

        // 心跳机制相关
        this.heartbeatInterval = 3000;
        this.heartbeatTimer = null;
        this.heartbeatMsg = JSON.stringify({
            type: "ping",
        });
    }

    addMessageHandler(handler) {
        this.messageHandlers.add(handler);
        return () => this.removeMessageHandler(handler); // 返回移除函数
    }
    removeMessageHandler(handler) {
        this.messageHandlers.delete(handler);
    }

    async connect() {
        this.accountStore = useAccountStore();
        if (!this.accountStore.isLogin) {
            console.warn("未登录,不连接ws");
            return;
        }
        if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
            console.warn("ws已连接,不需要重复连接");
            return;
        }
        this.url = `${apiConfig.wsUrl}?token=${useAccountStore().token}`;
        this.ws = new WebSocket(this.url);

        this.ws.onopen = () => {
            console.log("[WS] 连接成功");
            this.startHeartbeat();
        };

        this.ws.onmessage = (event) => {
            let data;
            try {
                data = JSON.parse(event.data);
            } catch (e) {
                console.error("[WS] 消息解析失败:", e);
                return;
            }

            //处理消息
            switch (data.type) {
                case "pone":
                    console.log("[WS] 收到心跳响应");
                    break;
                case "offLine":
                    ElMessage.info("您已被超管断开后台链接");
                    this.accountStore.loginOut();
                    break;
            }
            //事件派发模式,处理其他组件内额外的事件
            this.messageHandlers.forEach((handler) => handler(data));
        };

        this.ws.onclose = (event) => {
            console.warn("[WS] 连接关闭", event);
            let reason = this.getWsCloseReason(event.code);
            ElNotification({
                title: "提示",
                message: reason,
                type: "warning",
            });
            this.ws = null;
            this.stopHeartbeat();
            if (!this.isManualClose) {
                this.reconnect();
            }
        };

        this.ws.onerror = (err) => {
            console.error("[WS] 错误:", err);
            this.stopHeartbeat();
            this.ws?.close();
            this.ws = null;
        };
    }

    startHeartbeat() {
        this.stopHeartbeat(); // 防止重复设置
        this.heartbeatTimer = setInterval(() => {
            if (this.ws && this.ws.readyState === WebSocket.OPEN) {
                this.ws.send(this.heartbeatMsg);
            }
        }, this.heartbeatInterval);
    }

    stopHeartbeat() {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
            this.heartbeatTimer = null;
        }
    }

    send(data) {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify(data));
        } else {
            console.warn("[WS] 发送失败，连接尚未打开");
        }
    }

    disconnect() {
        this.isManualClose = true;
        this.stopHeartbeat();
        if (this.ws) {
            this.ws.close();
            this.ws = null;
        }
    }

    reconnect() {
        if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
        this.reconnectTimer = setTimeout(() => {
            console.log("[WS] 正在尝试重连...");
            this.connect();
        }, this.reconnectInterval);
    }

    //ws关闭事件代码
    getWsCloseReason(code) {
        switch (code) {
            case 1000:
                return "连接正常关闭";
            case 1001:
                return "服务器断开或页面关闭";
            case 1002:
                return "协议错误，无法建立连接";
            case 1003:
                return "收到不可识别的数据格式";
            case 1005:
                return "连接失败，未返回状态码";
            case 1006:
                return "服务器拒绝连接,认证失败或服务未响应";
            case 1007:
                return "数据格式错误，连接被关闭";
            case 1008:
                return "连接被拒绝，权限或策略不符";
            case 1009:
                return "发送数据过大，连接被服务器断开";
            case 1011:
                return "服务器内部错误，连接中断";
            default:
                return "ws关闭,未知错误（代码: " + code + "）";
        }
    }

    messageHandlers() {}
}

export const wsManager = new WSManager();
